#include "arch.h"
#include "config.h"
#include "time.h"
#include "irq.h"

#define BCD2Hex(number) (((number >> 4) & 0xf) * 10 + (number & 0xf))

/* jiffies should be defined as volatile */
volatile unsigned long jiffies=0;
volatile unsigned long jiffies_div10=0;
volatile unsigned long s_dealyCounterPer10Us; // Timer ticks per 10 microseconds
volatile unsigned long s_caculateTicks = 0x3fff;
volatile unsigned long s_delayTicks;
volatile unsigned long s_delayTicks1;

void TimerInit(void)
{
    unsigned short startTime, endTime, diffTime;
    volatile int i = 0;


    rCLKCON |= 1 << 8;

    // Use time4
    ClearPending(BIT_TIMER4);

    //  Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}
    //  {prescaler value} = 0~255
    //  {divider value} = 2, 4, 8, 16
    //
    // PCLK = 400000000 / 6, Timer freq =  4166667Hz,  24us per 100 ticks.
    // Max Interval = 65535 * 1 / 4166667Hz = 15728us
    rTCFG0  &= ~0x00ff00;        //prescaler = 0
    rTCFG1  = (rTCFG1  & ~(0x0f0000)) | 0x030000;  //divider value = 3, mux0 = 1/16

    rTCNTB4 = 0xffff;
    rTCON  = (rTCON & ~(0xf00000)) | (1 << 21);
    rTCON  = (rTCON & ~(0xf00000)) | /*(1 << 22) |*/ (1 << 20); // Start timer


    // Caculate the delay time
    startTime = rTCNTO4;
    while (i < s_caculateTicks) i++;
    endTime = rTCNTO4;
    if (endTime < startTime) {
        diffTime = startTime - endTime;
    }
    else {
        diffTime = 0xffff - (endTime - startTime);
    }
    s_dealyCounterPer10Us = (s_caculateTicks * 1000/ ((unsigned long)(diffTime) * 24)) ;


    rTCON &= ~(1 << 20); // Stop timer



}

/* returns the time in seconds */
u32  TimerGetTime(void)
{
    return BCD2Hex(rBCDSEC); // BUGBUG: 0-59s, temp code
//    return rTCNTO4;
}

/* returns the time in 1/100seconds */
u32  TimerGetCentiTime(void)
{
    return 0;
//    return((u32) jiffies/(TIMER_TICK_PER_SEC*100));
}

// The accuracy is about 10 microsenconds
void ostdelay(int uSec)
{
#if 1
    volatile int i = 0;
    int n10uSec;

    n10uSec = (uSec + 9) / 10;
    s_delayTicks = n10uSec * s_dealyCounterPer10Us;

    while (i < s_delayTicks) i++;

#else
    // Test code
    int i;
    for (i = 0; i < uSec * 1000; i++);
#endif

    return ;
}

void msleep(unsigned int ms)
{
//    while (ms > 1000) {
//        ostdelay(1000 * 1000);
//        ms -= 1000;
//    }
    ostdelay(1000 * ms);
}

void msleep_cli(unsigned int ms)
{
//    unsigned long init_jiffies;
//
//    init_jiffies = OSCR;
//
//    while( (init_jiffies + (unsigned long)(ms / 10) ) > OSCR ) {;}

}
